/**
 * @file upsAPP.c
 * @author  xiaowine (xiaowine@sina.cn)
 * @brief
 * @version 01.00
 * @date    2021-07-27
 *
 * @copyright Copyright (c) {2020}  xiaowine
 *
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2021-07-27 <td>1.0     <td>wangh     <td>内容
 * </table>
 * ******************************************************************
 * *                   .::::
 * *                 .::::::::
 * *                ::::::::::
 * *             ..:::::::::::
 * *          '::::::::::::
 * *            .:::::::::
 * *       '::::::::::::::..        女神助攻,流量冲天
 * *            ..::::::::::::.     永不宕机,代码无bug
 * *          ``:::::::::::::::
 * *           ::::``:::::::::'        .:::
 * *          ::::'   ':::::'       .::::::::
 * *        .::::'      ::::     .:::::::'::::
 * *       .:::'       :::::  .:::::::::' ':::::
 * *      .::'        :::::.:::::::::'      ':::::
 * *     .::'         ::::::::::::::'         ``::::
 * * ...:::           ::::::::::::'              ``::
 * *```` ':.          ':::::::::'                  ::::.
 * *                   '.:::::'                    ':'````.
 * ******************************************************************
 */

/* Private includes ----------------------------------------------------------*/
#include "upsAPP.h"
#include <rtthread.h>
#include <string.h>
#include "spiTransmit.h"
#include "stdio.h"

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/
#define UPS_PRIORITY   10
#define UPS_STACK_SIZE 2048
#define UPS_TIMESLICE  5
/* Private macro -------------------------------------------------------------*/

static rt_err_t QPIPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t MPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QSPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QMDPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QGSPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QFSPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QWSPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QWFPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QMODPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QRIPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t FPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t Q3PVPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t Q3PCPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t Q3OCPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t Q3YVPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QYFPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t Q3YCPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t Q3LDPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QRPVPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBYVPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBYFPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QPARPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QFLAGPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVFWPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVFW2Pro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVFW3Pro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVERPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QIDPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBVPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QNBVPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QLDLPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QHEPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QFREPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QSKPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QSKTPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBDRPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QTPRPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t Q5Pro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QCHGCPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBUSPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBUSPPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBUSNPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVBPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVCPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVLINEPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVBYPPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QMAXWPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QMXVAPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QPDPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBCOPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QIPTPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QNLPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBATPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QTVPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QVSOCPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QBTAHPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QPSTPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QMFPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QTIMEPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QSTZPro(uint8_t ups, char *buff, uint8_t len);
static rt_err_t QDWHPro(uint8_t ups, char *buff, uint8_t len);
/* Private variables ---------------------------------------------------------*/
const cmd_ups_t commandMap[] = {
    {"QPI\r",    '(', '\r', 1,  QPIPro   }, // UPS_QPI
    {"M\r",      '(', '\r', 1,  MPro     }, // UPS_M
    {"QS\r",     '(', '\r', 1,  QSPro    }, // UPS_QS
    {"QMD\r",    '(', '\r', 1,  QMDPro   }, // UPS_QMD
    {"QGS\r",    '(', '\r', 75, QGSPro   }, // UPS_QGS
    {"QFS\r",    '(', '\r', 1,  QFSPro   }, // UPS_QFS
    {"QWS\r",    '(', '\r', 65, QWSPro   }, // UPS_QWS
    {"QWF\r",    '(', '\r', 1,  QWFPro   }, // UPS_QWF
    {"QMOD\r",   '(', '\r', 1,  QMODPro  }, // UPS_QMOD
    {"QRI\r",    '(', '\r', 1,  QRIPro   }, // UPS_QRI
    {"F\r",      '(', '\r', 1,  FPro     }, // UPS_F
    {"Q3PV\r",   '(', '\r', 1,  Q3PVPro  }, // UPS_Q3PV
    {"Q3PC\r",   '(', '\r', 1,  Q3PCPro  }, // UPS_Q3PC
    {"Q3OC\r",   '(', '\r', 1,  Q3OCPro  }, // UPS_Q3OC
    {"Q3YV\r",   '(', '\r', 1,  Q3YVPro  }, // UPS_Q3YV
    {"QYF\r",    '(', '\r', 1,  QYFPro   }, // UPS_QYF
    {"Q3YC\r",   '(', '\r', 1,  Q3YCPro  }, // UPS_Q3YC
    {"Q3LD\r",   '(', '\r', 1,  Q3LDPro  }, // UPS_Q3LD
    {"QRPV\r",   '(', '\r', 1,  QRPVPro  }, // UPS_QRPV
    {"QBYV\r",   '(', '\r', 1,  QBYVPro  }, // UPS_QBYV
    {"QBYF\r",   '(', '\r', 1,  QBYFPro  }, // UPS_QBYF
    {"QPAR\r",   '(', '\r', 1,  QPARPro  }, // UPS_QPAR
    {"QFLAG\r",  '(', '\r', 1,  QFLAGPro }, // UPS_QFLAG
    {"QVFW\r",   '(', '\r', 1,  QVFWPro  }, // UPS_QVFW
    {"QVFW2\r",  '(', '\r', 1,  QVFW2Pro }, // UPS_QVFW2
    {"QVFW3\r",  '(', '\r', 1,  QVFW3Pro }, // UPS_QVFW3
    {"QVER\r",   '(', '\r', 1,  QVERPro  }, // UPS_QVER
    {"QID\r",    '(', '\r', 1,  QIDPro   }, // UPS_QID
    {"QBV\r",    '(', '\r', 1,  QBVPro   }, // UPS_QBV
    {"QNBV\r",   '(', '\r', 1,  QNBVPro  }, // UPS_QNBV
    {"QLDL\r",   '(', '\r', 1,  QLDLPro  }, // UPS_QLDL
    {"QHE\r",    '(', '\r', 1,  QHEPro   }, // UPS_QHE
    {"QFRE\r",   '(', '\r', 1,  QFREPro  }, // UPS_QFRE
    {"QSK\r",    '(', '\r', 1,  QSKPro   }, // UPS_QSK
    {"QSKT\r",   '(', '\r', 1,  QSKTPro  }, // UPS_QSKT
    {"QBDR\r",   '(', '\r', 1,  QBDRPro  }, // UPS_QBDR
    {"QTPR\r",   '(', '\r', 1,  QTPRPro  }, // UPS_QTPR
    {"Q5\r",     '(', '\r', 1,  Q5Pro    }, // UPS_Q5
    {"QCHGC\r",  '(', '\r', 1,  QCHGCPro }, // UPS_QCHGC
    {"QBUS\r",   '(', '\r', 1,  QBUSPro  }, // UPS_QBUS
    {"QBUSP\r",  '(', '\r', 1,  QBUSPPro }, // UPS_QBUSP
    {"QBUSN\r",  '(', '\r', 1,  QBUSNPro }, // UPS_QBUSN
    {"QVB\r",    '(', '\r', 1,  QVBPro   }, // UPS_QVB
    {"QV\r",     '(', '\r', 1,  QVPro    }, // UPS_QV
    {"QVC\r",    '(', '\r', 1,  QVCPro   }, // UPS_QVC
    {"QVLINE\r", '(', '\r', 1,  QVLINEPro}, // UPS_QVLINE
    {"QVBYP\r",  '(', '\r', 1,  QVBYPPro }, // UPS_QVBYP
    {"QMAXW\r",  '(', '\r', 1,  QMAXWPro }, // UPS_QMAXW
    {"QMXVA\r",  '(', '\r', 1,  QMXVAPro }, // UPS_QMXVA
    {"QPD\r",    '(', '\r', 1,  QPDPro   }, // UPS_QPD
    {"QBCO\r",   '(', '\r', 1,  QBCOPro  }, // UPS_QBCO
    {"QIPT\r",   '(', '\r', 1,  QIPTPro  }, // UPS_QIPT
    {"QNL\r",    '(', '\r', 1,  QNLPro   }, // UPS_QNL
    {"QBAT\r",   '(', '\r', 18, QBATPro  }, // UPS_QBAT
    {"QTV\r",    '(', '\r', 1,  QTVPro   }, // UPS_QTV
    {"QVSOC\r",  '(', '\r', 1,  QVSOCPro }, // UPS_QVSOC
    {"QBTAH\r",  '(', '\r', 1,  QBTAHPro }, // UPS_QBTAH
    {"QPST\r",   '(', '\r', 1,  QPSTPro  }, // UPS_QPST
    {"QMF\r",    '(', '\r', 1,  QMFPro   }, // UPS_QMF
    {"QTIME\r",  '(', '\r', 1,  QTIMEPro }, // UPS_QTIME
    {"QSTZ\r",   '(', '\r', 1,  QSTZPro  }, // UPS_QSTZ
    {"QDWH\r",   '(', '\r', 1,  QDWHPro  }, // UPS_QDWH
};
#include "sys_conf.h"
uint8_t   contextArea[128] = {0};
uint8_t  *qpiValuePoint    = contextArea;
upsQs_t  *qsValuePoint     = (upsQs_t *)(contextArea + 1);
upaQmd_t *qmdPoint         = (upaQmd_t *)(contextArea + 1 + sizeof(upsQs_t));

q3gs_t   *contextQ3GS = (q3gs_t *)contextArea;
uint8_t  *contextQFS  = (contextArea + sizeof(q3gs_t));
uint32_t *contextQ3WS = (uint32_t *)(contextArea + sizeof(q3gs_t) + 1);
/* Public variables ---------------------------------------------------------*/
static rt_thread_t tid1       = RT_NULL;
static rt_thread_t tid2       = RT_NULL;
static rt_mq_t     upsRXmq[2] = {RT_NULL, RT_NULL};

const spiUart_t uartPort[2] = {SPIUSART8, SPIUSART9};
/* Private function prototypes -----------------------------------------------*/
struct rx_msg {
    uint8_t msgData[128];
    uint8_t msgSize;
};
/* Private functions ---------------------------------------------------------*/
static rt_err_t upsCommand(uint8_t ups, _upsInquiryCmd_t cmd);
/* Private user code ---------------------------------------------------------*/

#include "sys_conf.h"
#include "sys_status.h"
extern sys_reg_st g_sys;  // global parameter declairation
static void       upsEntry(void *parameter)
{
    uint32_t ups = (uint32_t)parameter;
    rt_thread_delay(5000);
    rt_kprintf("upsEntry:%d\r\n", ups);
    while (1) {
        rt_err_t rec;
        rt_thread_delay(1000);
        rec = upsCommand(ups, UPS_QGS);
        if (rec == RT_EOK) {
            sys_set_remap_status(UPS_COM_STS_NO, ups, 1);
        } else {
            sys_set_remap_status(UPS_COM_STS_NO, ups, 0);
        }
        rt_thread_delay(200);
        upsCommand(ups, UPS_QWS);
        rt_thread_delay(200);
        upsCommand(ups, UPS_QBAT);
    }
}

int upsAppInit(void)
{
    /* 初始化消息队列 */
    upsRXmq[UPS1] = rt_mq_create("ups1RXmq", sizeof(struct rx_msg), 3, RT_IPC_FLAG_FIFO);
    upsRXmq[UPS2] = rt_mq_create("ups2RXmq", sizeof(struct rx_msg), 3, RT_IPC_FLAG_FIFO);

    /* 创建线程 1,名称是 thread1,入口是 upsEntry*/
    tid1 = rt_thread_create("ups1thread", upsEntry, (void *)UPS1, UPS_STACK_SIZE, UPS_PRIORITY, UPS_TIMESLICE);
    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);
    else {
        rt_kprintf("ups1thread creat error\r\n");
    }
    rt_thread_delay(50);
    tid2 = rt_thread_create("ups2thread", upsEntry, (void *)UPS2, UPS_STACK_SIZE, UPS_PRIORITY, UPS_TIMESLICE);
    /* 如果获得线程控制块,启动这个线程 */
    if (tid2 != RT_NULL)
        rt_thread_startup(tid2);
    else {
        rt_kprintf("ups2thread creat error\r\n");
    }
    return 0;
}
INIT_APP_EXPORT(upsAppInit);

rt_err_t upsRXmqPush(uint8_t ups, uint8_t *buff, uint8_t length)
{
    struct rx_msg msg = {0};
    if (upsRXmq[ups] == RT_NULL) {
        return -RT_ERROR;
    }

    if (length > 120) {
        length = 120;
    }

    msg.msgSize = length;
    memcpy(msg.msgData, buff, msg.msgSize);
    if (upsRXmq[ups])
        return rt_mq_send(upsRXmq[ups], &msg, sizeof(struct rx_msg));
    else
        return RT_EOK;
}

void upsRXmqClear(uint8_t ups)
{
    rt_err_t      status;
    struct rx_msg msg = {0};
    do {
        status = rt_mq_recv(upsRXmq[ups], &msg, sizeof(struct rx_msg), 10);
    } while (status == RT_EOK);
}
static uint8_t upsRec(uint8_t ups, uint8_t *cache, rt_uint32_t timeout)
{
    rt_err_t      status;
    struct rx_msg msg;
    status = rt_mq_recv(upsRXmq[ups], &msg, sizeof(struct rx_msg), timeout);
    if (status == RT_EOK) {
        memcpy(cache, msg.msgData, msg.msgSize);
        return msg.msgSize;
    } else {
        // rt_kprintf("ups%dRec timeout\r\n", ups);
    }

    return 0;
}
static rt_err_t upsSend(uint8_t ups, _upsInquiryCmd_t cmd)
{
    return spiMsgQPush(uartPort[ups], (uint8_t *)commandMap[cmd].cmd, strlen(commandMap[cmd].cmd));
}
static rt_err_t upsCommand(uint8_t ups, _upsInquiryCmd_t cmd)
{
    uint8_t len;
    uint8_t temp[128] = {0};
    // rt_kprintf("ups%d,cmd%d**\r\n", ups, cmd, len);
    upsRXmqClear(ups);
    upsSend(ups, cmd);

    len = upsRec(ups, temp, 800);
    if ((commandMap[cmd].process != NULL) && (len >= commandMap[cmd].bklen)) {
        char *p;
        p = strchr((void *)temp, commandMap[cmd].bkHead);
        if (p != NULL) {
            len -= (p - (char *)temp);
            if (len >= commandMap[cmd].bklen) {
                if (*(p + commandMap[cmd].bklen) == commandMap[cmd].bkEnd)
                    commandMap[cmd].process(ups, p, len);
                else {
                    rt_kprintf("ups%d,cmd%d,errLen:%d bklen:%d end:%02x,temp:%s **\r\n", ups, cmd, len, commandMap[cmd].bklen, *(p + commandMap[cmd].bklen), temp);
                    return -RT_ERROR;
                }
            } else {
                rt_kprintf("ups:%d errLen:%d,temp:%s **\r\n", ups, len, temp);
                return -RT_ERROR;
            }
        } else {
            rt_kprintf("ups:%d err head:%s **\r\n", ups, temp);
            return -RT_ERROR;
        }
        return RT_EOK;
    }
    if (len > 0) {
        rt_kprintf("ups%d,cmd%d len:%d temp:%s **\r\n", ups, cmd, len, temp);
    }
    if (len == 0) {
        return -RT_ETIMEOUT;
    }
    return RT_EOK;
}
/*
(220.2 50.0 220.0 50.0 027.0 100 345.8 344.9 241.0 241.5 045.0 100011000000\r
(220.2 50.0 220.0 50.0 027.0 100 345.8 344.9 241.0 241.5 045.0 100011000000

(0000000000000000000000000000000000000000000000000000000000000000
(1111111111111111111111111111111111111111111111111111111111111111
*/
/**
 * @brief   Protocol ID Inquiry
 * @param  buff  string
 * @param  len   length of string
 */
static rt_err_t QPIPro(uint8_t ups, char *buff, uint8_t len)
{
    int qpi_v;
    sscanf((void *)buff, "(PI%02d\r", &qpi_v);
    *qpiValuePoint = qpi_v;
    return RT_EOK;
}
/**
 * @brief  UPS password----Special for off-line
 * @param  buff  string
 * @param  len   length of string
 */
static rt_err_t MPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
/**
 * @brief  UPS Status parameters Inquiry----Special for off-line
 * @param  buff  string
 * @param  len   length of string
 */
static rt_err_t QSPro(uint8_t ups, char *buff, uint8_t len)
{
    float mmm, nnn, ppp, rrr, sss, ttt;
    int   qqq;
    char  upsStatus[20];
    //"(MMM.M NNN.N PPP.P QQQ RR.R SS.S TT.T 76543210\r"
    sscanf(buff, "(%f %f %f %d %f %f %f %s\r", &mmm, &nnn, &ppp, &qqq, &rrr, &sss, &ttt, upsStatus);

    qsValuePoint->inputVoltage        = mmm * 10;
    qsValuePoint->inputFaultValtage   = nnn * 10;
    qsValuePoint->outputVoltage       = ppp * 10;
    qsValuePoint->outputLoad          = qqq;
    qsValuePoint->outputFrequency     = rrr * 10;
    qsValuePoint->batteryVoltage      = sss * 10;
    qsValuePoint->internalTemperature = ttt * 10;
    // qsValuePoint->upsStatus           = 0;
    for (qqq = 0; qqq < 8; qqq++) {
        // qsValuePoint->upsStatus |= ((upsStatus[qqq] == '1') ? (1 << qqq) : 0);
    }

    // sscanf(buff, "%[ ]%[^ ]%[ ]%[^ ] %[^ ] %[^ ] %[^ ] %[^ ] %[^ ] %[^ ]", TTTTTTTTTTTTTTT, TTTTTTTTTTTTTTT, WWWWWWW,
    //        WWWWWWW, KKK, P_P, MMM, NNN, RR, BB_B);
    return RT_EOK;
}
/**
 * @brief  Model Inquiry
 * @param  buff  string
 * @param  len   length of string
 */
static rt_err_t QMDPro(uint8_t ups, char *buff, uint8_t len)
{
    char  ttt[15];
    char  www[7];
    int   kk, p1, p2, mmm, nnn, rr;
    float bbb;

    //(TTTTTTTTTTTTTTT WWWWWWW KK P/P MMM NNN RR BB.B\r
    sscanf(buff, "(%[^ ] %[^ ] %d %d/%d %d %d %d %f\r", ttt, www, &kk, &p1, &p2, &mmm, &nnn, &rr, &bbb);
    return RT_EOK;
}
/**
 * @brief  The general status parameters inquiry
 * @param  buff  string
 * @param  len   length of string
 * "(220 2 50 0 220 0 50 0 027 0 100 345 8 344 9 241 0 241 5 045 0 100011000000";
 * "(220.2 50.0 220.0 50.0 027.0 100 345.8 344.9 241.0 241.5 045.0 100011000001\r"
 * "(MMM.M HH.H LLL.L NN.N QQQ.Q DDD KKK.K VVV.V SSS.S XXX.X TTT.T 987654321001\r"
 */

static rt_err_t QGSPro(uint8_t ups, char *buff, uint8_t len)
{
    float mmm, hh, ll, nn, qq, kkk, vv, ss, xx, tt;
    int   ddd;
    char  upsStatusChar[120];

    if (len < commandMap[UPS_QGS].bklen) {
        rt_kprintf("QGSPro too small:%d %s \r\n", strlen(buff), buff);
        return -RT_ERROR;
    }
    sscanf(buff, "(%f %f %f %f %f %d %f %f %f ---.- %f %s\r", &mmm, &hh, &ll, &nn, &qq, &ddd, &kkk, &vv, &ss, &tt, upsStatusChar);
    g_sys.status.mbm.UPS[ups].UPSQgs.inputVoltage    = mmm * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.inputFrequency  = hh * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.outputVoltage   = ll * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.outputFrequency = nn * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.outputCurrent   = qq * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.outputLoad      = ddd;
    g_sys.status.mbm.UPS[ups].UPSQgs.PBusVoltage     = kkk * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.NBusVoltage     = vv * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.PBatteryVoltage = ss * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.NBatteryVoltage = xx * 10;
    g_sys.status.mbm.UPS[ups].UPSQgs.MAXTemperature  = tt * 10;
    for (ddd = 0; ddd < 12; ddd++) {
        g_sys.status.mbm.UPS[ups].UPSQgs.Status.StatusWord |= ((upsStatusChar[ddd] == '1') ? (0x800 >> ddd) : 0);
    }
    return RT_EOK;
}
static rt_err_t QFSPro(uint8_t ups, char *buff, uint8_t len)
{
    int qfsValue = 0;
    sscanf(buff, "(%02d\r", &qfsValue);
    *contextQFS = qfsValue;
    // sscanf(buff, "(%02d\r", contextQFS);

    // sscanf(buff, "%[ ]%[^ ]%[ ]%[^ ] %[^ ] %[^ ] %[^ ] %[^ ] %[^ ] %[^ ]", TTTTTTTTTTTTTTT, TTTTTTTTTTTTTTT, WWWWWWW,
    //        WWWWWWW, KKK, P_P, MMM, NNN, RR, BB_B);
    return RT_EOK;
}
static rt_err_t QWSPro(uint8_t ups, char *buff, uint8_t len)
{
    uint8_t i;
    g_sys.status.mbm.UPS[ups].UPSQws.WARN[0].warnWord = 0;
    g_sys.status.mbm.UPS[ups].UPSQws.WARN[1].warnWord = 0;
    g_sys.status.mbm.UPS[ups].UPSQws.WARN[2].warnWord = 0;
    g_sys.status.mbm.UPS[ups].UPSQws.WARN[3].warnWord = 0;
    for (i = 0; i < 64; i++) {
        g_sys.status.mbm.UPS[ups].UPSQws.WARN[i / 16].warnWord |= ((*(buff + 1 + i) == '1') ? (1 << (i % 16)) : 0);
    }
    // rt_kprintf("ups%d warn:%04x %04x %04x %04x\r\n", ups, g_sys.status.mbm.UPS[ups].UPSQws.WARN[0].warnWord, g_sys.status.mbm.UPS[ups].UPSQws.WARN[1].warnWord,
    //            g_sys.status.mbm.UPS[ups].UPSQws.WARN[2].warnWord, g_sys.status.mbm.UPS[ups].UPSQws.WARN[3].warnWord);
    return RT_EOK;
}
static rt_err_t QWFPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QMODPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QRIPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t FPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t Q3PVPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t Q3PCPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t Q3OCPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t Q3YVPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QYFPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t Q3YCPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t Q3LDPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QRPVPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBYVPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBYFPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QPARPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QFLAGPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVFWPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVFW2Pro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVFW3Pro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVERPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QIDPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBVPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QNBVPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QLDLPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QHEPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QFREPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QSKPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QSKTPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBDRPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QTPRPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t Q5Pro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QCHGCPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBUSPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBUSPPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBUSNPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVBPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVCPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVLINEPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVBYPPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QMAXWPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QMXVAPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QPDPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBCOPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QIPTPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QNLPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBATPro(uint8_t ups, char *buff, uint8_t len)
{
    float r_r;
    int   xx, yy, zzz;
    if (len < commandMap[UPS_QBAT].bklen) {
        rt_kprintf("QBATPro too small:%d %s \r\n", strlen(buff), buff);
        return -RT_ERROR;
    }
    sscanf(buff, "(BAT%d %d %d %f\r", &xx, &yy, &zzz, &r_r);

    g_sys.status.mbm.UPS[ups].UPSQgs.batCapacity = zzz;
    return RT_EOK;
}
static rt_err_t QTVPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QVSOCPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QBTAHPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QPSTPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QMFPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QTIMEPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QSTZPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
static rt_err_t QDWHPro(uint8_t ups, char *buff, uint8_t len)
{
    *buff = *buff;
    return RT_EOK;
}
